package com.jeesite.modules.digitalize.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.modules.digitalize.constants.RelationTypeEnum;
import com.jeesite.modules.digitalize.constants.TaskReviewStatusEnum;
import com.jeesite.modules.digitalize.constants.TaskStatusEnum;
import com.jeesite.modules.digitalize.dao.DigitalizeTaskDao;
import com.jeesite.modules.digitalize.entity.*;
import com.jeesite.modules.digitalize.entity.dto.DigitalizeTaskAuditDTO;
import com.jeesite.modules.digitalize.entity.dto.DigitalizeTaskDTO;
import com.jeesite.modules.digitalize.entity.dto.DigitalizeTaskQuery;
import com.jeesite.modules.digitalize.entity.vo.DigitalizeTaskInfoVO;
import com.jeesite.modules.digitalize.entity.vo.DigitalizeTaskVO;
import com.jeesite.modules.digitalize.util.minio.MinioFileUtil;
import com.jeesite.modules.digitalize.util.pdf.PdfUtil;
import com.jeesite.modules.digitalize.util.response.ResultVo;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.service.UserService;
import com.jeesite.modules.sys.utils.UserUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.jeesite.modules.digitalize.constants.MessageConstants.*;

/**
 * (DigitalizeTask)表服务实现类
 *
 * @author makejava
 * @since 2023-11-11 17:05:12
 */
@Service
public class DigitalizeTaskService extends ServiceImpl<DigitalizeTaskDao, DigitalizeTask> {

    @Resource
    private DigitalizeTaskReviewService digitalizeTaskReviewService;

    @Resource
    DigitalizeMessageService digitalizeMessageService;
    @Resource
    DigitalizeBindService digitalizeBindService;
    @Resource
    DigitalizeTaskAnnexService digitalizeTaskAnnexService;
    @Resource
    private UserService userService;
    @Resource
    private DigitalizeComponentNoteService digitalizeComponentNoteService;

    @Resource
    @Lazy
    private DigitalizePlanDetailService digitalizePlanDetailService;

    @Resource
    @Lazy
    private DigitalizePlanService digitalizePlanService;

    @Resource
    private PdfUtil pdfUtil;

    @Resource
    private MinioFileUtil minioFileUtil;

    @Resource
    private DigitalizeTaskArchiveService digitalizeTaskArchiveService;

    private void suppendUserName(List<DigitalizeTaskVO> list) {
        Map<String, User> userMap = new HashMap<>();

        list.forEach(chartVo -> {
            User user = userMap.computeIfAbsent(chartVo.getCurrentUserId(), userId -> userService.get(userId));
            if (user != null) {
                chartVo.setCurrentUserName(user.getUserName());
            }
        });
    }

    public Page<DigitalizeTaskVO> pageList(DigitalizeTaskQuery query) {
        Page<DigitalizeTaskVO> page = new Page(query.getPageNo(), query.getPageSize());
        List<DigitalizeTaskVO> result = this.baseMapper.pageList(page, query, UserUtils.getUser().getId());
        suppendUserName(result);
        page.setRecords(result);
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo saveOrUpdate(DigitalizeTaskDTO dto) {
        TaskStatusEnum status = TaskStatusEnum.getByCode(dto.getTaskStatus());
        if (status == null) {
            return ResultVo.failure("任务状态不正确");
        }
        if (dto.getId() != null) {
            DigitalizeTask task = this.getById(dto.getId());
            if (task == null) {
                return ResultVo.failure("任务不存在");
            }
            if (!TaskStatusEnum.NOT_SUBMITTED.getCode().equals(task.getTaskStatus())) {
                return ResultVo.failure("任务已在进行中");
            }
        }
        DigitalizeTask digitalizeTask = BeanUtil.copyProperties(dto, DigitalizeTask.class);
        digitalizeTask.setSequence(dto.getReviewList().size()).setCurrentSequence(1);
        digitalizeTask.setSubmitDate(TaskStatusEnum.IN_PROGRESS.equals(status) ? new Date() : null);
        this.saveOrUpdate(digitalizeTask);

        digitalizeTaskAnnexService.deleteAndAdd(digitalizeTask.getId(), null, dto.getFileUrlList());
        // 删除旧的 新增标签和笔记
        digitalizeBindService.deleteAndAdd(digitalizeTask.getId(), dto.getLabelIdList(), RelationTypeEnum.TASK_LABEL);
        digitalizeBindService.deleteAndAdd(digitalizeTask.getId(), dto.getNoteIdList(), RelationTypeEnum.TASK_NOTE);

        digitalizeTaskReviewService.lambdaUpdate().eq(DigitalizeTaskReview::getTaskId, digitalizeTask.getId()).remove();
        List<DigitalizeTaskReview> reviewList = BeanUtil.copyToList(dto.getReviewList(), DigitalizeTaskReview.class).stream().sorted(Comparator.comparing(DigitalizeTaskReview::getSequence)).collect(Collectors.toList());

        for (DigitalizeTaskReview digitalizeTaskReview : reviewList) {
            digitalizeTaskReview.setTaskId(digitalizeTask.getId());
            digitalizeTaskReview.setStatus(TaskStatusEnum.NOT_SUBMITTED.getCode());
        }
        if (TaskStatusEnum.IN_PROGRESS.equals(status)) {
            // 通知
            reviewList.get(0).setStatus(TaskStatusEnum.IN_PROGRESS.getCode());
            digitalizeMessageService.sendMsg(reviewList.get(0).getReviewerId(), NEW_TASK, String.format(NEW_TASK_CONTENT, UserUtils.getUser().getUserName(), digitalizeTask.getTaskName()), dto.getProjectId());
        }
        digitalizeTaskReviewService.saveBatch(reviewList);
        if (digitalizeTask.getPlanDetailId() != null) {
            this.digitalizePlanDetailService.lambdaUpdate().set(DigitalizePlanDetail::getTaskId, digitalizeTask.getId()).set(DigitalizePlanDetail::getTaskName, digitalizeTask.getTaskName()).eq(DigitalizePlanDetail::getId, digitalizeTask.getPlanDetailId()).update();
        }
        return ResultVo.success(digitalizeTask);
    }

    @Transactional
    public Boolean delete(List<Long> idList) {
        if (CollectionUtil.isEmpty(idList)) {
            return false;
        }
        boolean b = this.removeByIds(idList);
        digitalizeTaskReviewService.lambdaUpdate().in(DigitalizeTaskReview::getTaskId, idList).remove();
        digitalizeTaskAnnexService.lambdaUpdate().in(DigitalizeTaskAnnex::getTaskId, idList).remove();
        digitalizeBindService.lambdaUpdate().in(DigitalizeBind::getFatherId, idList).remove();
        this.digitalizePlanDetailService.lambdaUpdate().in(DigitalizePlanDetail::getTaskId, idList)
                .set(DigitalizePlanDetail::getTaskId, null).set(DigitalizePlanDetail::getTaskName, null).update();
        return b;
    }

    public ResultVo getInfo(Long id) {
        DigitalizeTask task = this.getById(id);
        if (task == null) {
            return ResultVo.failure("任务不存在");
        }
        DigitalizeTaskInfoVO digitalizeTaskInfoVO = BeanUtil.copyProperties(task, DigitalizeTaskInfoVO.class);
        List<DigitalizeTaskReview> list = digitalizeTaskReviewService.lambdaQuery().eq(DigitalizeTaskReview::getTaskId, id).list();
        digitalizeTaskInfoVO.setReviewList(list);
        User user = userService.get(digitalizeTaskInfoVO.getCreateBy());
        digitalizeTaskInfoVO.setUserName(user != null ? user.getUserName() : digitalizeTaskInfoVO.getCreateBy());
        digitalizeTaskInfoVO.setFileList(digitalizeTaskAnnexService.lambdaQuery().eq(DigitalizeTaskAnnex::getTaskId, id).isNull(DigitalizeTaskAnnex::getTaskDetailId).list());
        List<Integer> labelIdList = getSonIdList(digitalizeTaskInfoVO.getId(), RelationTypeEnum.TASK_LABEL);
        if (CollectionUtil.isNotEmpty(labelIdList)) {
            digitalizeTaskInfoVO.setLabelIdList(labelIdList);
            digitalizeTaskInfoVO.setLabelList(digitalizeComponentNoteService.lambdaQuery().in(DigitalizeComponentNote::getId, labelIdList).list());
        }

        List<Integer> noteIdList = getSonIdList(digitalizeTaskInfoVO.getId(), RelationTypeEnum.TASK_NOTE);

        if (CollectionUtil.isNotEmpty(noteIdList)) {
            digitalizeTaskInfoVO.setNoteIdList(noteIdList);
            digitalizeTaskInfoVO.setNoteList(digitalizeComponentNoteService.lambdaQuery().in(DigitalizeComponentNote::getId, noteIdList).list());
        }

        list.stream().filter(item -> item.getSequence().equals(task.getCurrentSequence())).findFirst().ifPresent(item -> {
            digitalizeTaskInfoVO.setCanAudit(TaskStatusEnum.IN_PROGRESS.getCode().equals(digitalizeTaskInfoVO.getTaskStatus()) && Objects.equals(item.getReviewerId(), UserUtils.getUser().getId()));
            digitalizeTaskInfoVO.setCanReply(TaskStatusEnum.IN_PROGRESS.getCode().equals(digitalizeTaskInfoVO.getTaskStatus()) && Objects.equals(item.getReviewerId(), UserUtils.getUser().getId()) && StringUtils.isBlank(item.getReply()));
        });

        list.stream().forEach(item -> {
            User reviewer = userService.get(item.getReviewerId());
            item.setUserName(reviewer != null ? reviewer.getUserName() : item.getReviewerId());
            item.setFileList(digitalizeTaskAnnexService.lambdaQuery().eq(DigitalizeTaskAnnex::getTaskDetailId, item.getId()).list());

            List<Integer> labelIdList2 = getSonIdList(item.getId(), RelationTypeEnum.TASK_DETAIL_LABEL);

            if (CollectionUtil.isNotEmpty(labelIdList2)) {
                item.setLabelIdList(labelIdList2);
                item.setLabelList(digitalizeComponentNoteService.lambdaQuery().in(DigitalizeComponentNote::getId, labelIdList2).list());
            }

            List<Integer> noteIdList2 = getSonIdList(item.getId(), RelationTypeEnum.TASK_DETAIL_NOTE);

            if (CollectionUtil.isNotEmpty(noteIdList2)) {
                item.setNoteIdList(noteIdList2);
                item.setNoteList(digitalizeComponentNoteService.lambdaQuery().in(DigitalizeComponentNote::getId, noteIdList2).list());
            }
        });

        //查询构建id集合
        if (null != task.getPlanDetailId()) {
            digitalizeTaskInfoVO.setComponentIdList(digitalizePlanDetailService.getComponentListByPlanDetailId(Long.valueOf(task.getPlanDetailId())));
            //根据planDetailId 查询 componentId
            digitalizeTaskInfoVO.setComponentId(digitalizePlanService.getComponentIdByPlanDetailId(task.getPlanDetailId()));
        } else {
            digitalizeTaskInfoVO.setComponentIdList("");
            digitalizeTaskInfoVO.setComponentId(0L);
        }

        return ResultVo.success(digitalizeTaskInfoVO);
    }

    private List<Integer> getSonIdList(Long fatherId, RelationTypeEnum taskLabel) {
        List<Integer> labelIdList = digitalizeBindService.lambdaQuery().eq(DigitalizeBind::getFatherId, fatherId).eq(DigitalizeBind::getType, taskLabel.getCode()).list().stream().map(DigitalizeBind::getSonId).collect(Collectors.toList());
        return labelIdList;
    }

    @Transactional
    public ResultVo audit(DigitalizeTaskAuditDTO dto) {
        DigitalizeTask task = this.getById(dto.getTaskId());
        if (task == null || !TaskStatusEnum.IN_PROGRESS.getCode().equals(task.getTaskStatus())) {
            return ResultVo.failure("任务状态不正确");
        }
        DigitalizeTaskReview review = digitalizeTaskReviewService.lambdaQuery().eq(DigitalizeTaskReview::getTaskId, dto.getTaskId()).eq(DigitalizeTaskReview::getSequence, task.getCurrentSequence()).one();
        if (review == null) {
            return ResultVo.failure("当前流程为空");
        }
        if (!UserUtils.getUser().getId().equals(review.getReviewerId())) {
            return ResultVo.failure("审批用户不正确");
        }
        if (StringUtils.isNotBlank(review.getReply()) && StringUtils.isNotBlank(dto.getReply())) {
            return ResultVo.failure("该审批已答复过了");
        }
        digitalizeTaskReviewService.lambdaUpdate()
                .eq(DigitalizeTaskReview::getId, review.getId())
                .set(StringUtils.isNoneEmpty(dto.getReply()), DigitalizeTaskReview::getReply, dto.getReply())
                .set(DigitalizeTaskReview::getRemarks, dto.getRemarks())
                .set(DigitalizeTaskReview::getStatus, dto.getStatus())
                .update();

        digitalizeTaskAnnexService.deleteAndAdd(review.getTaskId(), review.getId(), dto.getFileUrlList());
        // 删除旧的 新增标签和笔记
        digitalizeBindService.deleteAndAdd(review.getId(), dto.getLabelIdList(), RelationTypeEnum.TASK_DETAIL_LABEL);
        digitalizeBindService.deleteAndAdd(review.getId(), dto.getNoteIdList(), RelationTypeEnum.TASK_DETAIL_NOTE);

        if (TaskReviewStatusEnum.COMPLETED.getCode().equals(dto.getStatus()) || TaskReviewStatusEnum.REJECTED.getCode().equals(dto.getStatus())) {
            // 审核通过或者驳回
            if (TaskReviewStatusEnum.COMPLETED.getCode().equals(dto.getStatus())) {
                // 审核通过
                if (task.getCurrentSequence().equals(task.getSequence())) {
                    // 最后一步
                    task.setTaskStatus(TaskStatusEnum.COMPLETED.getCode());
                    digitalizeMessageService.sendMsg(task.getCreateBy(), FINISH_TASK, String.format(FINISH_TASK, UserUtils.getUser().getUserName(), task.getTaskName()), task.getProjectId());
                } else {
                    task.setCurrentSequence(task.getCurrentSequence() + 1);
                    DigitalizeTaskReview one = digitalizeTaskReviewService.lambdaQuery().eq(DigitalizeTaskReview::getTaskId, dto.getTaskId()).eq(DigitalizeTaskReview::getSequence, task.getSequence()).one();
                    digitalizeMessageService.sendMsg(one.getReviewerId(), PROCESS_TASK, String.format(PROCESS_TASK_CONTENT, UserUtils.getUser().getUserName(), task.getTaskName()),task.getProjectId());
                    digitalizeTaskReviewService.updateById(one.setStatus(TaskReviewStatusEnum.IN_PROGRESS.getCode()));
                }
            } else {
                // 审核驳回
                task.setTaskStatus(TaskStatusEnum.REJECTED.getCode());
                digitalizeMessageService.sendMsg(task.getCreateBy(), PROCESS_TASK, String.format(PROCESS_TASK_REJECT_CONTENT, UserUtils.getUser().getUserName(), task.getTaskName()), task.getProjectId());
            }
            this.updateById(task);
        } else {
            digitalizeMessageService.sendMsg(task.getCreateBy(), REPLY_TASK, String.format(REPLY_TASK_CONTENT, UserUtils.getUser().getUserName(), task.getTaskName()), task.getProjectId());
        }
        return ResultVo.success();
    }

    public ResultVo archive(Long id, User user) {
        ResultVo<DigitalizeTaskInfoVO> info = getInfo(id);
        if (info.isFail()) {
            throw new RuntimeException("任务不存在");
        }
        DigitalizeTaskInfoVO taskInfo = info.getData();
        List<User> userList = userService.findList(new User());
        Map<String, String> userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getUserName));
        //创建pdf文件
        MultipartFile pdf = pdfUtil.createPdf(taskInfo, user, userMap);
        ResultVo resultVo = minioFileUtil.uploadFile(pdf);
        if (!resultVo.isFail()) {
            digitalizeTaskArchiveService.save(new DigitalizeTaskArchive()
                    .setTaskId(id).setFileName(pdf.getOriginalFilename())
                    .setFileUrl(ObjectUtils.isNotEmpty(resultVo.getData()) ? resultVo.getData().toString() : null)
                    .setFileSize(String.valueOf(pdf.getSize())).setDelStatus(0));
            //修改状态为已归档
            taskInfo.setTaskStatus(TaskStatusEnum.ARCHIVED.getCode());
            taskInfo.setUpdateBy(UserUtils.getUser().getId());
            taskInfo.setUpdateDate(new Date());
            this.updateById(taskInfo);
        }
        digitalizeMessageService.sendMsg(taskInfo.getCreateBy(), ARCHIVE_TASK, String.format(ARCHIVE_TASK_CONTENT, UserUtils.getUser().getUserName(), taskInfo.getTaskName()), taskInfo.getProjectId());
        return resultVo;
    }

    public List<DigitalizeTaskVO> selectWarnTask() {
        return this.baseMapper.selectWarnTask();
    }
}

